is_pptp() { local p; network_get_protocol p "$1"; [ "${p:0:4}" = "pptp" ]; }
is_softether() { local d; network_get_device d "$1"; [ "${d:0:4}" = "vpn_" ]; }
is_supported_interface() { { is_lan "$1" || is_disabled_interface "$1"; } && return 1; str_contains_word "$supported_interface" "$1" || { ! is_ignored_interface "$1" && { is_wan "$1" || is_wan6 "$1" || is_tunnel "$1"; }; } || is_ignore_target "$1" || is_xray "$1"; }
+is_netbird() { local d; network_get_device d "$1"; [ "${d:0:2}" = "wt" ]; }
is_tailscale() { local d; network_get_device d "$1"; [ "${d:0:9}" = "tailscale" ]; }
is_tor() { [ "$(str_to_lower "$1")" = "tor" ]; }
is_tor_running() { ! is_ignored_interface 'tor' && [ -s "$torConfigFile" ] && str_contains "$(ubus call service list "{ 'name': 'tor' }" | jsonfilter -e '@.tor.instances.*.running')" 'true' && return 0 || return 1; }
-is_tunnel() { is_dslite "$1" || is_l2tp "$1" || is_oc "$1" || is_ovpn "$1" || is_pptp "$1" || is_softether "$1" || is_tailscale "$1" || is_tor "$1" || is_wg "$1"; }
+is_tunnel() { is_dslite "$1" || is_l2tp "$1" || is_oc "$1" || is_ovpn "$1" || is_pptp "$1" || is_softether "$1" || is_netbird "$1" || is_tailscale "$1" || is_tor "$1" || is_wg "$1"; }
is_url() { is_url_file "$1" || is_url_dl "$1"; }
is_url_dl() { is_url_ftp "$1" || is_url_http "$1" || is_url_https "$1"; }
is_url_file() { [ "$1" != "${1#file://}" ]; }
#!/bin/sh
# When using pbr with dnsmasq's nft set support, a domain-based policy will not take effect until
# the remote domain name has been resolved by dnsmasq. Resolve all domain names in pbr policies in advance.
+# shellcheck disable=SC3043
(
- timeout_nft='10'
- timeout_dnsmasq='20'
- pipe_ubus="/tmp/pipe.ubus.$$"
- pipe_nslookup="/tmp/pipe.nslookup.$$"
- log_abort='domain names in policies not resolved'
+ pipe_nslookup="/var/run/${packageName}.nslookup.$$"
- # shellcheck disable=SC2154
- output()
- {
- msg="$*"
- msg=$(printf '%b' "$msg" | sed 's/\x1b\[[0-9;]*m//g')
+ output() {
+ local msg="$*"
+
+ msg="$(printf '%b' "$msg" | sed 's/\x1b\[[0-9;]*m//g')"
+ # shellcheck disable=SC2154
logger -t "$packageName [$$]" "$(printf '%b' "$msg")"
}
- nft_ready()
- {
+ nft_ready() {
+ local timeout_nft='10'
+
while ! /usr/sbin/nft list sets 'inet' | grep -q "pbr"; do
[ "$timeout_nft" -eq '0' ] && {
- output "Pbr's nft sets not found, $log_abort $__FAIL__"
return 1
}
- sleep '1' && timeout_nft=$((timeout_nft - 1))
+ sleep '1' && timeout_nft="$((timeout_nft - 1))"
done
}
- run_nslookup()
- {
- output=$(nslookup "$1" 127.0.0.1) && { echo '0' > "$pipe_nslookup"; return; }
- reason=$(printf '%s' "$output" | grep -Eo -m 1 'NXDOMAIN|SERVFAIL|timed out') && \
+ run_nslookup() {
+ local output reason
+
+ output="$(nslookup "$1" 127.0.0.1)" && { echo '0' > "$pipe_nslookup"; return; }
+ reason="$(printf '%s' "$output" | grep -Eo -m 1 'NXDOMAIN|SERVFAIL|timed out')" && \
output "$_WARNING_ Lookup failed for $domain ($reason)"
echo '1' > "$pipe_nslookup"
}
- # shellcheck disable=SC2162
- nslookup_tracker()
- {
- while read ec; do
- entries=$((entries + 1))
- [ "$ec" -eq '1' ] && errors=$((errors + 1))
+ nslookup_tracker() {
+ local entries errors
+
+ while read -r rc; do
+ entries="$((entries + 1))"
+ [ "$rc" -eq '1' ] && errors="$((errors + 1))"
done < "$pipe_nslookup"
output "Finished resolving $entries domain names in policies (${errors:-0} failed) $__OK__"
}
- [ -n "$resolverSetSupported" ] || {
- output "Resolver set support disabled, $log_abort $__FAIL__"
- exit
- }
- mkfifo "$pipe_ubus"
- mkfifo "$pipe_nslookup"
- ubus listen -m 'ubus.object.add' > "$pipe_ubus" & ubus_listen_pid=$!
+ main() {
+ local pipe_ubus="/var/run/${packageName}.ubus.$$"
+ local timeout_dnsmasq='20'
+ local msg_abort='domain names in policies not resolved'
+ local dnsmasq_restarted ubus_listen_pid event domain entries
+ local rc='0'
- # shellcheck disable=SC3045
- while read -t "$timeout_dnsmasq" -r event; do
- echo "$event" | grep -q "dnsmasq.dns" || continue
- dnsmasq_restarted='1'
- # shellcheck disable=SC2154
- [ -f "$packageDnsmasqFile" ] || {
- output "File $packageDnsmasqFile not found, $log_abort $__FAIL__"
- break
+ [ -n "$resolverSetSupported" ] || {
+ output "Resolver set support disabled, $msg_abort $__FAIL__"
+ rc='1'
+ return "$rc"
}
- nft_ready || break
- nslookup_tracker & exec 3>"$pipe_nslookup"
-
- (
- output "Resolving domain names in policies..."
- while IFS='/' read -r _ domain _; do
- [ -n "$domain" ] && run_nslookup "$domain" &
- entries=$((entries + 1))
- done < "$packageDnsmasqFile"
- wait
- )
+ mkfifo "$pipe_ubus"
+ mkfifo "$pipe_nslookup"
+ # The subshell may be necessary for "$!" to expand to a correct value
+ ( exec ubus listen -m 'ubus.object.add' > "$pipe_ubus" ) &
+ ubus_listen_pid="$!"
- exec 3>&-
- break
- done < "$pipe_ubus"
+ # shellcheck disable=SC3045
+ while read -t "$timeout_dnsmasq" -r event; do
+ echo "$event" | grep -q "dnsmasq.dns" || continue
+ dnsmasq_restarted='1'
+ # shellcheck disable=SC2154
+ [ -f "$packageDnsmasqFile" ] || {
+ output "File $packageDnsmasqFile not found, $msg_abort $__FAIL__"
+ rc='1'
+ break
+ }
+ nft_ready || {
+ output "Pbr's nft sets not found, $msg_abort $__FAIL__"
+ rc='1'
+ break
+ }
+ nslookup_tracker & exec 3>"$pipe_nslookup"
+ (
+ output "Resolving domain names in policies..."
+ while IFS='/' read -r _ domain _; do
+ [ -n "$domain" ] && run_nslookup "$domain" &
+ entries="$((entries + 1))"
+ done < "$packageDnsmasqFile"
+ wait
+ )
+ exec 3>&-
+ break
+ done < "$pipe_ubus"
- [ -n "$dnsmasq_restarted" ] || output "Dnsmasq hasn't restarted, $log_abort $__FAIL__"
- kill "$ubus_listen_pid"
- rm "$pipe_ubus"
- rm "$pipe_nslookup"
+ [ -n "$dnsmasq_restarted" ] || {
+ output "Dnsmasq hasn't restarted, $msg_abort $__FAIL__"
+ rc='1'
+ }
+ kill "$ubus_listen_pid"
+ rm -f "$pipe_ubus"
+ rm -f "$pipe_nslookup"
+ return "$rc"
+ }
+
+ main
+ return "$?"
) &